{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以下是此大整数加减法算法的设计核心要点：\n",
    "\n",
    "1. **字符串存储大数绝对值**\n",
    "   - 使用 `std::string` 保存任意长度整数的绝对值部分，避免受内置整数类型位宽限制。\n",
    "   - 通过单独的布尔标志 `isNegative_` 维护符号信息，运算时先处理符号逻辑，再委托绝对值运算。\n",
    "2. **按位手工实现加法与减法**\n",
    "   - **加法**：从最低位（字符串尾部）开始逐位相加，使用布尔变量 `carry` 记录进位，将每一步结果暂存后整体反转。\n",
    "   - **减法**：在保证被减数绝对值不小于减数的前提下，从低到高逐位相减，借位通过布尔变量 `borrow` 记录，最终清理高位冗余零并反转结果。\n",
    "   - 进位/借位的布尔标志确保处理连续进位或连续借位的情况。\n",
    "3. **符号与绝对值比较的预处理**\n",
    "   - 运算：若符号相同则直接相加，符号保留；若符号不同则转化为绝对值较大者减较小者。\n",
    "   - 运算：转换为加法（被减数加上减数的相反数），从而复用加法流程。\n",
    "   - 通过 `compareAbsolute` 函数比较两个绝对值大小，为决定运算顺序与结果符号提供依据。\n",
    "4. **结果归一化与边界处理**\n",
    "   - 每次运算完毕后调用 `normalizeZero()`，保证零的表示为 `\"0\"` 且符号为正。\n",
    "\n",
    "- 输入解析与构造时去除前导零，确保内部表示一致。\n",
    "- 加减法后的结果字符串若出现前导零，通过反向删除或统一函数清理。\n",
    "\n",
    "1. **接口友好、实现精简**\n",
    "   - 重载输出运算符 `<<` 与加减运算符，让外部调用保持接近原生类型的体验。\n",
    "   - 静态助手函数 `addAbsolute`、`subtractAbsolute`、`compareAbsolute` 仅面向绝对值，避免重复逻辑并保持类内职责清晰。\n",
    "\n",
    "综上，通过“符号分离 + 字符串逐位运算 + 结果归一化”的核心设计，使 BigInt 能够在不依赖额外库的情况下完成可靠的大数加减运算。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [],
   "source": [
    "! g++ -std=c++17 -O2 bigintaddsubtest.cpp -lgtest -lgtest_main -pthread -o bigintaddsubtest && ./bigintaddsubtest"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# TDD"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| Step | 操作              | 新测试                    | 代码更新要点                            |\n",
    "| ---- | ----------------- | ------------------------- | --------------------------------------- |\n",
    "| 0    | 项目骨架          | ❌                         | 仅占位                                  |\n",
    "| 1    | 默认构造 & 输出   | ✅ `DefaultIsZero`         | 类初始结构，输出写死 \"0\"                |\n",
    "| 2    | 字符串构造 & 解析 | ✅ `ParseSignedString`     | 添加成员变量、解析函数                  |\n",
    "| 3    | long long 构造    | ✅ `ConstructFromLongLong` | 转换 long long，归零符号                |\n",
    "| 4    | 同号加法          | ✅ `AdditionSameSign`      | 引入 addAbsolute，部分实现 operator+    |\n",
    "| 5    | 异号加法          | ✅ `AdditionDifferentSign` | 引入 compare / subtract，补齐 operator+ |\n",
    "| 6    | 减法              | ✅ `Subtraction`           | operator- 基于加法实现                  |\n",
    "| 7    | 边界补充          | ✅ `ZeroNormalization` 等  | 验证归零、非数字输入等                  |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## step-0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[==========] Running 0 tests from 0 test suites.\n",
      "[==========] 0 tests from 0 test suites ran. (0 ms total)\n",
      "[  PASSED  ] 0 tests.\n"
     ]
    }
   ],
   "source": [
    "! cd TDD/00 && g++ -std=c++17 -O2 bigInt_test.cpp -lgtest -lgtest_main -pthread -o bigInt_test && ./bigInt_test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## step-1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./00/bigintaddsub.h\t2025-10-10 10:41:56.229971000 +0800\n",
      "+++ ./01/bigintaddsub.h\t2025-10-10 10:56:51.717061100 +0800\n",
      "@@ -1 +1,16 @@\n",
      "-#pragma once\n",
      "\\ No newline at end of file\n",
      "+#pragma once\n",
      "+\n",
      "+#include <iostream>\n",
      "+#include <string>\n",
      "+\n",
      "+class BigInt {\n",
      "+public:\n",
      "+    // Step1: 默认构造初始化内部状态为 0\n",
      "+    BigInt() {}\n",
      "+\n",
      "+    // Step1: 输出运算符直接打印常量 \"0\"\n",
      "+    friend std::ostream& operator<<(std::ostream& os, const BigInt&) {\n",
      "+        os << \"0\";\n",
      "+        return os;\n",
      "+    }\n",
      "+};\n",
      "\\ No newline at end of file\n"
     ]
    }
   ],
   "source": [
    "! cd TDD && diff -u ./00/bigintaddsub.h ./01/bigintaddsub.h"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[==========] Running 1 test from 1 test suite.\n",
      "[----------] Global test environment set-up.\n",
      "[----------] 1 test from BigIntStep1\n",
      "[ RUN      ] BigIntStep1.DefaultIsZero\n",
      "[       OK ] BigIntStep1.DefaultIsZero (0 ms)\n",
      "[----------] 1 test from BigIntStep1 (0 ms total)\n",
      "\n",
      "[----------] Global test environment tear-down\n",
      "[==========] 1 test from 1 test suite ran. (0 ms total)\n",
      "[  PASSED  ] 1 test.\n"
     ]
    }
   ],
   "source": [
    "! cd TDD/01 && g++ -std=c++17 -O2 bigInt_test.cpp -lgtest -lgtest_main -pthread -o bigInt_test && ./bigInt_test"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# step-02"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--- ./01/bigintaddsub.h\t2025-10-10 10:56:51.717061100 +0800\n",
      "+++ ./02/bigintaddsub.h\t2025-10-10 10:58:49.953027400 +0800\n",
      "@@ -1,16 +1,77 @@\n",
      "+// include/bigintaddsub.h\n",
      " #pragma once\n",
      " \n",
      "+#include <algorithm>\n",
      " #include <iostream>\n",
      " #include <string>\n",
      " \n",
      " class BigInt {\n",
      " public:\n",
      "-    // Step1: 默认构造初始化内部状态为 0\n",
      "-    BigInt() {}\n",
      "+    BigInt() : digits_(\"0\"), isNegative_(false) {}\n",
      " \n",
      "-    // Step1: 输出运算符直接打印常量 \"0\"\n",
      "-    friend std::ostream& operator<<(std::ostream& os, const BigInt&) {\n",
      "-        os << \"0\";\n",
      "+    explicit BigInt(const std::string& value) {\n",
      "+        parse(value);\n",
      "+    }\n",
      "+\n",
      "+    friend std::ostream& operator<<(std::ostream& os, const BigInt& obj) {\n",
      "+        if (obj.isNegative_ && obj.digits_ != \"0\") {\n",
      "+            os << '-';\n",
      "+        }\n",
      "+        os << obj.digits_;\n",
      "         return os;\n",
      "     }\n",
      "+\n",
      "+private:\n",
      "+    std::string digits_;\n",
      "+    bool isNegative_{false};\n",
      "+\n",
      "+    // Step2: 解析字符串并提取符号与数字\n",
      "+    void parse(const std::string& value) {\n",
      "+        if (value.empty()) {\n",
      "+            digits_ = \"0\";\n",
      "+            isNegative_ = false;\n",
      "+            return;\n",
      "+        }\n",
      "+\n",
      "+        std::size_t index = 0;\n",
      "+        if (value[index] == '+' || value[index] == '-') {\n",
      "+            isNegative_ = (value[index] == '-');\n",
      "+            ++index;\n",
      "+        } else {\n",
      "+            isNegative_ = false;\n",
      "+        }\n",
      "+\n",
      "+        digits_.clear();\n",
      "+        for (; index < value.size(); ++index) {\n",
      "+            char c = value[index];\n",
      "+            if (c >= '0' && c <= '9') {\n",
      "+                digits_.push_back(c);\n",
      "+            }\n",
      "+        }\n",
      "+\n",
      "+        if (digits_.empty()) {\n",
      "+            digits_ = \"0\";\n",
      "+            isNegative_ = false;\n",
      "+        } else {\n",
      "+            removeLeadingZeros();\n",
      "+        }\n",
      "+\n",
      "+        normalizeZero();\n",
      "+    }\n",
      "+\n",
      "+    // Step2: 清理解析后的前导零\n",
      "+    void removeLeadingZeros() {\n",
      "+        auto it = digits_.begin();\n",
      "+        while (it != digits_.end() - 1 && *it == '0') {\n",
      "+            ++it;\n",
      "+        }\n",
      "+        digits_.erase(digits_.begin(), it);\n",
      "+    }\n",
      "+\n",
      "+    // Step2: 将 \"-0\" 归一化为 \"0\"\n",
      "+    void normalizeZero() {\n",
      "+        if (digits_ == \"0\") {\n",
      "+            isNegative_ = false;\n",
      "+        }\n",
      "+    }\n",
      " };\n",
      "\\ No newline at end of file\n"
     ]
    }
   ],
   "source": [
    "! cd TDD && diff -u ./01/bigintaddsub.h ./02/bigintaddsub.h"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "C++17",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
